<template>
  <div>
    <!-- 
      作用：
          可以自定义ref对象，并对其依赖项 进行跟踪 和 更新页面 进行控制。
          解析：将ref对象划分为 数据跟踪 和 更新页面 两部分，病并变得可操作。

      ref对象：
          将数据变为一个响应式的数据
          对数据进行跟踪，数据一发生变化，界面也发生变化。  不可控。

      customRef
          跟踪 和 触发 两部分 分开， 变得 可控。
          可看成 ref对象 和 函数防抖 的结合
    -->

    <!-- 
      需求
          搜索框： 当输入完数据之后，再更新界面。
                ref写的话：我边写边更新，响应式的。
                customRef：写完之后（空档 时间）  再更新

          函数防抖： 
                  在多次触发同一函数时，只执行最后一次。
                  对于频繁操作，一段时间内不再触发，执行最后一次。  (一段时间  执行)
          函数节流：
                  同一函数被多次触发时，在一段时间内，只执行一次。 
                  对于频繁操作，一段时间内，只触发一次。  (执行  一段时间  执行)
     -->
    <h1>customRef</h1>
    <h1>{{ keyWordsRef }}</h1>
    <input type="text" v-model="keyWordsRef"><br>
    <h1>{{ keyWordsCustomRef }}</h1>
    <input type="text" v-model="keyWordsCustomRef">
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, customRef } from 'vue'

export default defineComponent({
  setup() {
    const keyWordsRef = ref('')
    //1、通过customRef自定义一个ref
    //value 值  初始值， 延迟时间 delay  注意函数中传参规定数据类型
    /*
        思路：固定写法
            1、创建一个自定义函数；函数中传入 value 初始值/收集到的值； delay 延迟时间
            2、函数返回customRef对象； 参数是回调函数，回调函数的参数track,trigger
                        track 告诉vue追踪数据； trigger 告诉vue 触发界面
            3、回调函数中返回一个对象，对象中有get和set两个函数。
    */

    //这块区域操作，就相当于完整的ref对象
    // //value 就是我们收集到的值 v-model，将其返回，是给setup函数中的数据返回
    // function useCustomRef<T>(value: T, delay = 500) {//注意函数中传参规定数据类型
    //   //返回自定义的ref对象  参数是回调函数
    //   //回调函数的参数：track,trigger
    //   //track 告诉vue追踪数据； trigger 告诉vue 触发界面
    //   return customRef((track, trigger) => {//等返回对象中的get和set写完，就不会划线报错了
    //     return {
    //       get() {
    //         track() //告诉vue 去追踪value
    //         return value  //我们传过来谁，就将谁返回去  返回给setup函数中的数据  view-->model
    //       },
    //       //更改新值，通过set劫持。
    //       set(newValue: T) {
    //         value = newValue;//将新值 赋予它
    //         //当value改变得到新值之后，通过trigger告诉vue更新界面
    //         trigger();//通过trigger告诉vue更新界面  将setup函数中更新的value值，给页面更新  model-->view
    //       }
    //     }
    //   })
    // }

    //value 就是我们收集到的值 v-model，将其返回，是给setup函数中的数据返回
    function useCustomRef<T>(value: T, delay = 500) {//注意函数中传参规定数据类型
      //返回自定义的ref对象  参数是回调函数
      //回调函数的参数：track,trigger
      //track 告诉vue追踪数据； trigger 告诉vue 触发界面
      return customRef((track, trigger) => {//等返回对象中的get和set写完，就不会划线报错了
        let timeOut:number;//定时器的结果是number类型
        return {
          get() {
            track() //告诉vue 去追踪value
            return value  //我们传过来谁，就将谁返回去  返回给setup函数中的数据  view-->model
          },
          //更改新值，通过set劫持。
          set(newValue: T) {
            clearTimeout(timeOut)//清除定时器  先清除定时器，后再设置定时器，实现函数防抖的效果
            //参数一：回调函数；  参数二：延迟时间
            timeOut = setTimeout(() => {
              value = newValue;//将新值 赋予它
              //当value改变得到新值之后，通过trigger告诉vue更新界面
              trigger();//通过trigger告诉vue更新界面  将setup函数中更新的value值，给页面更新  model-->view
            }, delay)

          }
        }
      })
    }
    const keyWordsCustomRef = useCustomRef('')
    return {
      keyWordsRef,
      keyWordsCustomRef
    }
  }
})
</script>

<style scoped>

</style>